﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using AForge.Robotics.Lego;
using System.IO.Ports;

namespace NxtSofor
{
    public partial class MainForm : Form
    {
        private ILegoDriver legoDriver = null;
        public List<Point> coor = new List<Point>();

        public int tick;

        public MainForm()
        {
            //SplashScreen.SplashScreen.Status = "NXTSoför uygulaması başlatılıyor ...";
            //System.Threading.Thread.Sleep(1500);

            InitializeComponent();

            //SplashScreen.SplashScreen.Status = "Donanım ayarları yükleniyor ...";
            //System.Threading.Thread.Sleep(2500);

            //SplashScreen.SplashScreen.Status = "NXTSoför uygulaması açılıyor.";
            //System.Threading.Thread.Sleep(1000);

            //SplashScreen.SplashScreen.Close();

        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                cbCOMPorts.Items.AddRange(SerialPort.GetPortNames());
                cbCOMPorts.SelectedIndex = cbCOMPorts.Items.Count - 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            cbLeftMotor.SelectedIndex = 1;
            cbRightMotor.SelectedIndex = 2;

            btnStop.Enabled = false;
            EnableControls(false);
        }

        private void EnableControls(bool status)
        {
            btnConnect.Enabled = !status;
            btnDisconnect.Enabled = status;
            btnChangeName.Enabled = status;
            btnSetMotors.Enabled = status;
            btnStopMotors.Enabled = status;
            btnForward.Enabled = status;
            btnBackward.Enabled = status;
            btnLeft.Enabled = status;
            btnRight.Enabled = status;
            btnTurnCW.Enabled = status;
            btnTurnCCW.Enabled = status;
            btnStart.Enabled = status;
            tbNXTsName.Enabled = status;
            tbMotion.Enabled = status;
            cbLeftMotor.Enabled = status;
            cbRightMotor.Enabled = status;
            nudLeftMotorPower.Enabled = status;
            nudRightMotorPower.Enabled = status;
        }

        private void btnBTControl_Click(object sender, EventArgs e)
        {
            string bthprops = "C:\\WINDOWS\\System32\\bthprops.cpl";
            string btcpl = "C:\\WINDOWS\\System32\\btcpl.cpl";

            try
            {
                System.Diagnostics.Process.Start(bthprops);
                System.Diagnostics.Process.Start(btcpl);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Bluetooth Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                System.Diagnostics.Process.Start("control");
            }
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            legoDriver = new LegoDriver(cbCOMPorts.Text);
            if (legoDriver.Connect())
            {
                GetInformation();
                EnableControls(true);
            }
            else
            {
                MessageBox.Show("Can not connect to NXT", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }

        private void GetInformation()
        {
            string nxtName;
            byte[] btAddress;
            int flashMemory;
            int batteryLevel;

            if (legoDriver.GetInformation(out nxtName, out btAddress, out flashMemory, out batteryLevel))
            {
                tbNXTsName.Text = nxtName;
                tbBluetoothAddress.Text = string.Format("{0} {1} {2} {3} {4} {5} {6}",
                    btAddress[0].ToString("X2"),
                    btAddress[1].ToString("X2"),
                    btAddress[2].ToString("X2"),
                    btAddress[3].ToString("X2"),
                    btAddress[4].ToString("X2"),
                    btAddress[5].ToString("X2"),
                    btAddress[6].ToString("X2")
                );

                int iFMemory = (int)(flashMemory / 1000);
                string strFMemory = iFMemory.ToString() + " %";
                
                toolTip1.SetToolTip(pbFlashMemory, strFMemory);
                pbFlashMemory.Value = iFMemory;

                int iBLevel = (int)(batteryLevel / 100);
                string strBLevel = iBLevel.ToString() + " %";
                
                toolTip1.SetToolTip(pbBatteryLevel, strBLevel);
                pbBatteryLevel.Value = iBLevel;
            }
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, 0, 0, 0, 0);
            }

            legoDriver.Disconnect();
            pbBatteryLevel.Value = 0;
            tbBluetoothAddress.Clear();
            pbFlashMemory.Value = 0;
            pbMotionStep.Value = 0;
            tbNXTsName.Clear();
            tbMotion.Clear();
            btnStop_Click(null, null);
            EnableControls(false);
        }

        private void btnChangeName_Click(object sender, EventArgs e)
        {
            if (tbNXTsName.Text != null && tbNXTsName.Text != "")
            {
                legoDriver.SetDeviceName(tbNXTsName.Text);
            }
        }

        private void btnSetMotors_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                //this.Text = "L " + cbLeftMotor.Text + " R " + cbRightMotor.Text;
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, 0, 0, 0, 0);
            }
            else 
            {
                MessageBox.Show("Left and right motor can not be the same", "Selection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnStopMotors_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, 0, 0, 0, 0);
            }
        }

        private void btnForward_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, (int)nudLeftMotorPower.Value, (int)nudRightMotorPower.Value, 50, 0);
            }
        }

        private void btnLeft_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, (int)(-nudLeftMotorPower.Value), (int)nudRightMotorPower.Value, 100, 0);
            }
        }

        private void btnRight_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, (int)nudLeftMotorPower.Value, (int)(-nudRightMotorPower.Value), 100, 0);
            }
        }

        private void btnBackward_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, (int)(-nudLeftMotorPower.Value), (int)(-nudRightMotorPower.Value), 50, 0);
            }
        }

        private void btnSetMotors_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData.ToString() == "W")
                btnForward_Click(null, null);
            if (e.KeyData.ToString() == "S")
                btnBackward_Click(null, null);
            if (e.KeyData.ToString() == "A")
                btnLeft_Click(null, null);
            if (e.KeyData.ToString() == "D")
                btnRight_Click(null, null);
            if (e.KeyData.ToString() == "Q")
                btnTurnCW_Click(null, null);
            if (e.KeyData.ToString() == "E")
                btnTurnCCW_Click(null, null);
            if (e.KeyData.ToString() == "Escape")
                btnStopMotors_Click(null, null);

        }

        private void btnTurnCW_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                btnSetMotors_Click(null, null);
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, (int)(nudLeftMotorPower.Value), (int)(-nudRightMotorPower.Value), 100, 250);
                
            }
        }

        private void btnTurnCCW_Click(object sender, EventArgs e)
        {
            if (cbLeftMotor.Text != cbRightMotor.Text)
            {
                btnSetMotors_Click(null, null);
                legoDriver.SetMotors(cbLeftMotor.Text, cbRightMotor.Text, (int)(-nudLeftMotorPower.Value), (int)(nudRightMotorPower.Value), 100, 250);

            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (tbMotion.Text != null || tbMotion.Text != "")
            {
                string motions = tbMotion.Text.Trim();
                motions = motions.Replace("\r\n", "|");

                motions = motions + "|0,0";

                string[] motion;
                motion = motions.Split('|');

                

                foreach (string mo in motion)
                {
                    coor.Add(strToPoint(mo));
                }

                pbMotionStep.Value = 0;
                timerMotion.Enabled = true;
                btnStart.Enabled = false;
                btnStop.Enabled = true;
            }
            else
            {
                MessageBox.Show("Motion list can not be empty.", "Motion list error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public Point strToPoint(string str)
        {
            Point p = new Point();
            string[] parts;

            parts = str.Split(',');

            p.X = Convert.ToInt32(parts[0]);
            p.Y = Convert.ToInt32(parts[1]);

            return p;
        }

        private void timerMotion_Tick(object sender, EventArgs e)
        {
            if (tick < coor.Count)
            {
                moveVehicle(coor, tick);
                tick++;
                pbMotionStep.Value = Convert.ToInt32((tick * pbMotionStep.Maximum) / coor.Count);
            }
            else
            {
                btnStart.Enabled = true;
                btnStop.Enabled = false;
            }
        }

        public void moveVehicle(List<Point> coordinate, int index)
        {
            if (coordinate[index].X > 0)
            {
                //forward
                btnForward_Click(null, null);
                System.Threading.Thread.Sleep(1000);
            }
            else if (coordinate[index].Y > 0) 
            {
                //turn cw
                btnTurnCW_Click(null, null);
                System.Threading.Thread.Sleep(2000);
            }
            else if (coordinate[index].X < 0)
            {
                //backward
                btnBackward_Click(null, null);
                System.Threading.Thread.Sleep(1000);
            }
            else if (coordinate[index].Y < 0)
            {
                //turn ccw
                btnTurnCCW_Click(null, null);
                System.Threading.Thread.Sleep(2000);
            }
            else
            { 
                //stop
                btnStopMotors_Click(null, null);
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            timerMotion.Enabled = false;
            btnStart.Enabled = true;
            btnStop.Enabled = false;
            if (legoDriver != null)
            {
                btnStopMotors_Click(null, null);
            }
        }

        private void btnAbout_Click(object sender, EventArgs e)
        {
            MessageBox.Show("This program is a part of \"Çok Silahşorlar\" project.\n\nFor more details:\nhttp://coksilahsorlar.blogspot.com\nhttp://code.google.com/p/coksilahsorlar", "About", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}
